package browser

import (
	"context"
	"errors"
	"fmt"
	"github.com/go-rod/rod"
	"github.com/go-rod/rod/lib/launcher"
	"github.com/go-rod/rod/lib/proto"
	"github.com/go-vgo/robotgo"
	"github.com/gogf/gf/container/gvar"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/text/gstr"
	"github.com/gogf/gf/util/gconv"
	"github.com/gogf/gf/util/grand"
	"github.com/ysmood/gson"
	"log"
	"syscall"
	"time"
	"unsafe"
)

var userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"
var (
	user32        = syscall.NewLazyDLL("user32.dll")
	findWindow    = user32.NewProc("FindWindowW")
	sendMessage   = user32.NewProc("SendMessageW")
	getWindowRect = user32.NewProc("GetWindowRect")
)

type Rect struct {
	Left   int32
	Top    int32
	Right  int32
	Bottom int32
}
type Status struct {
	Run         bool
	IsDownload  bool //是否下载
	IsCkDown    bool //是否在检查下载中
	DownloadNum int  //下载等待的次数
	DownloadMax int  //最大检测数

	Dn   int
	Msg  string
	Save bool //直接保存

	IsPause bool //是否等待
}

type Browser struct {
	MainBrowser *rod.Browser
	PageDown    *rod.Page
	PageShow    *rod.Page
	Daili       string
	Status
	Douttime int64 //代理失效时间

	Ctx context.Context
}

// NewBrowser 创建浏览器控制器
func NewBrowser(ctx context.Context, daili string) *Browser {
	t := &Browser{
		PageShow: nil,
	}
	t.MainBrowser = t.CreateBrowser(daili)
	t.Ctx = ctx
	t.PageDown = t.MainBrowser.MustPage("chrome://downloads/")
	return t
}

// CreateBrowser 创建浏览器
func (this *Browser) CreateBrowser(daili string) *rod.Browser {
	this.DelCache()
	path, _ := launcher.LookPath()
	la := launcher.New().
		Set("--disable-blink-features", "AutomationControlled"). //禁用自动化控制
		Set("--start-maximiz.ed").
		Set("--ignore-certificate-errors").
		Set("--disable-web-security").
		Delete("useAutomationExtension").
		Set("--disable-blink-features", "AutomationControlled").
		Bin(path)
	la = la.Delete("--headless")
	this.Daili = daili
	if this.Daili != "" {
		switch daili {
		case "zmhttp":
		case "xiaoxiong":
		default:
			la = la.Set("--proxy-server", daili)
		}
	}
	prefs := map[string]interface{}{
		"plugins": map[string]interface{}{
			"always_open_pdf_externally": true,
		},
		"safebrowsing": map[string]interface{}{
			"enabled": false,
		},
		"download": map[string]interface{}{
			"default_directory":   `D:\downpdf\`,
			"prompt_for_download": false,
			"directory_upgrade":   true,
		},
		"download_restrictions": 0, //允许下载
		"profile": map[string]interface{}{
			"default_content_setting_values": map[string]interface{}{
				"automatic_downloads":        1,
				"javascipt":                  1,
				"plugins":                    1,
				"popups":                     1,
				"geolocation":                1,
				"notifications":              1,
				"auto_select_certificate":    1,
				"fullscreen":                 1,
				"mouselock":                  1,
				"mixed_script":               1,
				"media_stream":               1,
				"media_stream_mic":           1,
				"media_stream_camera":        1,
				"protocol_handlers":          1,
				"ppapi_broker":               1,
				"midi_sysex":                 1,
				"push_messaging":             1,
				"ssl_cert_decisions":         1,
				"metro_switch_to_desktop":    1,
				"protected_media_identifier": 1,
				"app_banner":                 1,
				"site_engagement":            1,
				"durable_storage":            1,
				"running_insecure_content":   1,
			},
			"default_content_settings": map[string]interface{}{
				"popups": 0,
			},
		},
	}
	bs, _ := gvar.New(prefs).MarshalJSON()
	la.Preferences(string(bs))

	u := la.MustLaunch()

	brower := rod.New().ControlURL(u).MustConnect()
	return brower
}

// Close 关闭浏览器
func (this *Browser) Close() {
	//屏蔽错误
	defer func() {
		if r := recover(); r != nil {
			log.Println("浏览器关闭错误", r)
		}
	}()
	if this.MainBrowser != nil {
		this.MainBrowser.MustClose()
	}
}

// Sleep 等待加载完成，页面加载完成后，文档未加载完成，最多等5秒
func (this *Browser) Sleep(it ...int) int {
	log.Println("等待加载完成")
	t := 120
	if len(it) > 0 && it[0] > 0 {
		t = it[0]
	}
	//interactive 加载中
	//complete 加载完成
	//interactive 文档加载完成
	state := "complete"
	RunOK := false
	var run = make(chan bool)
	go func(sstate string) {
		defer func() {
			if r := recover(); r != nil {
				log.Println("页面等待错误")
				run <- true
			}
		}()
		if sstate == "" {
			sstate = "interactive"
		}
		html := ""
		htmlnoup := 0
		htmlnull := 0
		//如果10秒了还没有加载完成就做检测
		for {
			fmt.Print(".")
			if this.Ctx.Err() != nil {
				run <- true
				return
			}
			if RunOK {
				return
			}
			node := this.PageShow.MustEval(`()=>{let state=document.readyState;let html="";let body=document.getElementsByTagName("body");try{if(body.length>0){html=body[0].innerHTML;}}catch (e) {};return {state,html}}`)
			state = node.Get("state").String()
			nowhtml := node.Get("html").String()
			if state == "complete" {
				run <- true
				return
			}
			if nowhtml == "" {
				htmlnull++
			}
			if nowhtml != "" && state == "interactive" {
				if html != nowhtml {
					html = nowhtml
					htmlnoup = 0
				} else {
					htmlnoup++
				}
			}
			if htmlnoup > 5 || htmlnull > 5 {
				run <- true
				return
			}
			time.Sleep(time.Second)
		}
	}(state)
	after := time.NewTimer(time.Duration(t) * time.Second)
	defer after.Stop()

	rint := 0
	select {
	case <-run:
		log.Println("加载完成")
	case <-after.C:
		this.PageShow.StopLoading()
		log.Println("加载超时")
	}
	RunOK = true
	time.Sleep(time.Second * 1)
	log.Println("返回等待值", rint)
	return rint
}

// SleepAll 等待所有加载完成，直到文档加载完成
func (this *Browser) SleepAll(it ...int) int {
	log.Println("等待加载完成")
	t := 120
	if len(it) > 0 && it[0] > 0 {
		t = it[0]
	}
	//interactive 加载中
	//complete 加载完成
	//interactive 文档加载完成
	state := "complete"
	RunOK := false
	var run = make(chan bool)
	go func(sstate string) {
		defer func() {
			if r := recover(); r != nil {
				log.Println("页面等待错误")
				run <- true
			}
		}()
		if sstate == "" {
			sstate = "interactive"
		}
		//如果10秒了还没有加载完成就做检测
		for {
			fmt.Print(".")
			if this.Ctx.Err() != nil {
				run <- true
				return
			}
			if RunOK {
				return
			}
			node := this.PageShow.MustEval(`()=>{let state=document.readyState;let html="";let body=document.getElementsByTagName("body");try{if(body.length>0){html=body[0].innerHTML;}}catch (e) {};return {state,html}}`)
			state = node.Get("state").String()
			if state == "complete" {
				run <- true
				return
			}
			time.Sleep(time.Second)
		}
	}(state)
	after := time.NewTimer(time.Duration(t) * time.Second)
	defer after.Stop()

	rint := 0
	select {
	case <-run:
		log.Println("加载完成")
	case <-after.C:
		this.PageShow.StopLoading()
		log.Println("加载超时")
	}
	RunOK = true
	time.Sleep(time.Second * 1)
	log.Println("返回等待值", rint)
	return rint
}

// PageInfo 获取页面信息,返回页面标题，页面地址，页面内容
func (this *Browser) PageInfo() (title string, url string, html string) {
	if this.PageShow != nil {
		info := this.PageShow.MustInfo()
		return info.Title, info.URL, this.PageShow.MustHTML()
	}
	return "", "", ""
}

// ClosePage 清理多余的页面，保留下载页面
func (this *Browser) ClosePage() {
	log.Println("清理多余的页面")
	pages := this.MainBrowser.MustPages()
	//检测是否有下载页面
	dpage := false
	for _, page := range pages {
		if page.MustInfo().Title == "下载内容" || page.MustInfo().Title == "下载记录" {
			dpage = true
		} else {
			page.MustClose()
		}
	}
	if !dpage {
		this.PageDown = this.MainBrowser.MustPage("chrome://downloads/")
	}
	g.Log().Info("show页面清空")
	this.PageShow = nil
}

// ClearDown 清理下载文件，把下载页面的文件都清理掉，防止下次下载冲突
func (this *Browser) ClearDown() {
	log.Println("清理下载文件")
	//清理下载文件
	pages := this.MainBrowser.MustPages()
	dpage := false
	//检测是否有下载页面
	for _, page := range pages {
		if page.MustInfo().Title == "下载内容" || page.MustInfo().Title == "下载记录" {
			dpage = true
			page.MustEval(`()=>{try{
    document.querySelector("body > downloads-manager").shadowRoot.querySelector("#frb0").shadowRoot.querySelector("#cancel").click();
}catch (error){}
try {
    document.querySelector("body > downloads-manager").shadowRoot.querySelector("#toolbar").shadowRoot.querySelector("#clearAll").click()
} catch (error) {}
try {
    document.querySelector("body > downloads-manager").shadowRoot.querySelector("#toolbar").shadowRoot.querySelector("#moreActions").shadowRoot.querySelector("#icon").click()
    document.querySelector("body > downloads-manager").shadowRoot.querySelector("#toolbar").shadowRoot.querySelector("#moreActionsMenu > button.dropdown-item.clear-all").click()
}catch (error) {}
}`)
		}
	}
	if !dpage {
		this.PageDown = this.MainBrowser.MustPage("chrome://downloads/")
	}
}

// Page 默认打开页面
func (this *Browser) Page(url string) {
	log.Println("Page打开页面")
	defer func() {
		if r := recover(); r != nil {
			log.Println("Page打开页面错误", r)
			this.PageShow = nil
		}
	}()
	if this.PageShow == nil {
		this.PageShow = this.MainBrowser.MustPage("")
		this.PageShow.MustSetViewport(1920, 1080, 1, false)
		//this.PageShow.MustSetUserAgent(&proto.NetworkSetUserAgentOverride{UserAgent: userAgent})
		time.Sleep(time.Second * 1)
	} else {
		this.PageShow.Activate()
	}
	this.PageShow.Navigate(url)
}

// Page2 带ref正常打开页面
func (this *Browser) Page2(url string, ref ...string) error {
	log.Println("Page2打开页面", url)
	defer func() {
		if r := recover(); r != nil {
			log.Println("Page2打开页面错误", r)
			this.PageShow = nil
		}
	}()
	if this.PageShow == nil {
		this.PageShow = this.MainBrowser.MustPage("")
		this.PageShow.MustSetViewport(1920, 1080, 1, false)
		time.Sleep(time.Second * 1)
	} else {
		this.PageShow.Activate()
	}
	if url == "" {
		url = "about:blank"
	}
	refstr := ""
	if len(ref) > 0 {
		refstr = ref[0]
	}
	_ = this.PageShow.StopLoading()
	_, err := proto.PageNavigate{URL: url, Referrer: refstr}.Call(this.PageShow)
	if err != nil {
		return err
	}
	return nil
}

// Page3 传输信号模拟打开界面 关闭之前的页面
func (this *Browser) Page3(url string) error {
	log.Println("Page3打开页面")
	defer func() {
		if r := recover(); r != nil {
			log.Println("Page3打开页面错误", r)
			this.PageShow = nil
		}
	}()
	if this.PageShow == nil {
		this.PageShow = this.MainBrowser.MustPage("")
		this.PageShow.MustSetViewport(1920, 1080, 1, false)
		time.Sleep(time.Second * 1)
	} else {
		this.PageShow.Activate()
	}
	pages := this.MainBrowser.MustPages()
	num := len(pages)
	one := 256
	step := 238
	addx := (num-1)*step + one + 35
	addy := 20
	info, _ := this.PageShow.Info()
	WName := info.Title + " - Google Chrome"
	wname, err := syscall.UTF16PtrFromString(WName)
	if err != nil {
		panic(err)
	}
	r1, _, e1 := syscall.SyscallN(findWindow.Addr(), 0, uintptr(unsafe.Pointer(wname)))
	if r1 == 0 {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	if err != nil {
		return err
	}
	hwnd := r1
	// 模拟鼠标点击
	msgDown := uintptr(0x0201) // WM_LBUTTONDOWN
	msgUp := uintptr(0x0202)   // WM_LBUTTONUP

	var pt struct {
		X, Y int32
	}

	pt.X = int32(addx)
	pt.Y = int32(addy)
	lParam := uintptr(pt.Y)<<16 | uintptr(pt.X)
	// 发送鼠标按下消息
	syscall.SyscallN(sendMessage.Addr(), hwnd, msgDown, uintptr(1), lParam)

	// 发送鼠标释放消息
	syscall.SyscallN(sendMessage.Addr(), hwnd, msgUp, 0, lParam)
	time.Sleep(time.Second * 1)
	pt.X = int32(250)
	pt.Y = int32(63)
	lParam = uintptr(pt.Y)<<16 | uintptr(pt.X)
	syscall.SyscallN(sendMessage.Addr(), hwnd, msgDown, uintptr(1), lParam)
	syscall.SyscallN(sendMessage.Addr(), hwnd, msgUp, 0, lParam)

	time.Sleep(100 * time.Millisecond)
	//模拟键盘输入网址
	for _, c := range url {
		syscall.SyscallN(sendMessage.Addr(), hwnd, uintptr(0x0102), uintptr(c), 0)
		time.Sleep(10 * time.Millisecond)
	}
	//模拟回车键
	syscall.SyscallN(sendMessage.Addr(), hwnd, uintptr(0x0100), uintptr(13), 0)
	time.Sleep(time.Second * 1)

	if this.PageShow != nil {
		this.PageShow.MustClose()
	}
	pages = this.MainBrowser.MustPages()
	this.PageShow = pages[0]
	return nil
}

// Page32 传输信号模拟打开界面 不关闭之前的页面
func (this *Browser) Page32(url string) error {
	log.Println("Page32打开页面")
	defer func() {
		if r := recover(); r != nil {
			log.Println("Page32打开页面错误", r)
			this.PageShow = nil
		}
	}()
	if this.PageShow == nil {
		this.PageShow = this.MainBrowser.MustPage("")
		this.PageShow.MustSetViewport(1920, 1080, 1, false)
		time.Sleep(time.Second * 1)
	} else {
		this.PageShow.Activate()
	}
	pages := this.MainBrowser.MustPages()
	num := len(pages)
	one := 256
	step := 238
	addx := one + 35
	if num > 1 {
		addx = (num-1)*step + one + 35
	}
	addy := 20
	info, _ := this.PageShow.Info()
	WName := info.Title + " - Google Chrome"
	wname, err := syscall.UTF16PtrFromString(WName)
	if err != nil {
		panic(err)
	}
	r1, _, e1 := syscall.SyscallN(findWindow.Addr(), 0, uintptr(unsafe.Pointer(wname)))
	if r1 == 0 {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	if err != nil {
		return err
	}
	hwnd := r1
	// 模拟鼠标点击
	msgDown := uintptr(0x0201) // WM_LBUTTONDOWN
	msgUp := uintptr(0x0202)   // WM_LBUTTONUP

	var pt struct {
		X, Y int32
	}

	pt.X = int32(addx)
	pt.Y = int32(addy)
	lParam := uintptr(pt.Y)<<16 | uintptr(pt.X)
	// 发送鼠标按下消息
	syscall.SyscallN(sendMessage.Addr(), hwnd, msgDown, uintptr(1), lParam)

	// 发送鼠标释放消息
	syscall.SyscallN(sendMessage.Addr(), hwnd, msgUp, 0, lParam)
	time.Sleep(time.Second * 1)
	pt.X = int32(250)
	pt.Y = int32(63)
	lParam = uintptr(pt.Y)<<16 | uintptr(pt.X)
	syscall.SyscallN(sendMessage.Addr(), hwnd, msgDown, uintptr(1), lParam)
	syscall.SyscallN(sendMessage.Addr(), hwnd, msgUp, 0, lParam)

	time.Sleep(100 * time.Millisecond)
	//模拟键盘输入网址
	for _, c := range url {
		syscall.SyscallN(sendMessage.Addr(), hwnd, uintptr(0x0102), uintptr(c), 0)
		time.Sleep(10 * time.Millisecond)
	}
	//模拟回车键
	syscall.SyscallN(sendMessage.Addr(), hwnd, uintptr(0x0100), uintptr(13), 0)
	time.Sleep(time.Second * 1)

	pages = this.MainBrowser.MustPages()
	this.PageShow = pages[0]
	return nil
}

// Page4 操控鼠标模拟打开页面,使用robot打开
func (this *Browser) Page4(url string) error {
	log.Println("Page4打开页面")
	defer func() {
		if r := recover(); r != nil {
			log.Println("Page4打开页面错误", r)
			this.PageShow = nil
		}
	}()
	if this.PageShow == nil {
		this.PageShow = this.MainBrowser.MustPage("")
		this.PageShow.MustSetViewport(1920, 1080, 1, false)
		time.Sleep(time.Second * 1)
	} else {
		this.PageShow.Activate()
	}
	pages := this.MainBrowser.MustPages()
	num := len(pages)
	one := 256
	step := 238
	addx := (num-1)*step + one + 35
	addy := 20
	info, _ := this.PageShow.Info()
	WName := info.Title + " - Google Chrome"
	wname, err := syscall.UTF16PtrFromString(WName)
	if err != nil {
		panic(err)
	}
	rect := Rect{}
	r1, _, e1 := syscall.SyscallN(findWindow.Addr(), 0, uintptr(unsafe.Pointer(wname)))
	if r1 == 0 {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	if err != nil {
		return err
	}
	hwnd := r1
	//获取窗口位置
	getWindowRect.Call(hwnd, uintptr(unsafe.Pointer(&rect)))
	//点击
	robotgo.MoveClick(int(rect.Left)+addx, int(rect.Top)+addy)
	time.Sleep(time.Second * 2)
	//模拟键盘输入网址
	robotgo.TypeStr(url)
	//模拟回车键
	time.Sleep(time.Second * 1)
	robotgo.KeyTap("enter")
	time.Sleep(time.Second * 1)
	if this.PageShow != nil {
		this.PageShow.MustClose()
	}
	pages = this.MainBrowser.MustPages()
	this.PageShow = pages[0]
	return nil
}

// Page42 操控鼠标模拟打开页面，不关闭之前的，使用robot打开
func (this *Browser) Page42(url string) error {
	log.Println("Page4打开页面")
	defer func() {
		if r := recover(); r != nil {
			log.Println("Page4打开页面错误", r)
			this.PageShow = nil
		}
	}()
	if this.PageShow == nil {
		this.PageShow = this.MainBrowser.MustPage("")
		this.PageShow.MustSetViewport(1920, 1080, 1, false)
		time.Sleep(time.Second * 1)
	} else {
		this.PageShow.Activate()
	}
	pages := this.MainBrowser.MustPages()
	num := len(pages)
	one := 256
	step := 238
	addx := (num-1)*step + one + 35
	addy := 20
	info, _ := this.PageShow.Info()
	WName := info.Title + " - Google Chrome"
	wname, err := syscall.UTF16PtrFromString(WName)
	if err != nil {
		panic(err)
	}
	rect := Rect{}
	r1, _, e1 := syscall.SyscallN(findWindow.Addr(), 0, uintptr(unsafe.Pointer(wname)))
	if r1 == 0 {
		if e1 != 0 {
			err = error(e1)
		} else {
			err = syscall.EINVAL
		}
	}
	if err != nil {
		return err
	}
	hwnd := r1
	//获取窗口位置
	getWindowRect.Call(hwnd, uintptr(unsafe.Pointer(&rect)))
	//点击
	robotgo.MoveClick(int(rect.Left)+addx, int(rect.Top)+addy)
	time.Sleep(time.Second * 2)
	//模拟键盘输入网址
	robotgo.TypeStr(url)
	//模拟回车键
	time.Sleep(time.Second * 1)
	robotgo.KeyTap("enter")
	time.Sleep(time.Second * 1)
	pages = this.MainBrowser.MustPages()
	this.PageShow = pages[0]
	return nil
}

// Runjs 运行js
// js:js代码,返回数据把数据放到Rdata里
// DefData:默认返回值
//
//	返回值:json数据
func (this *Browser) Runjs(js string, DefData string) (ev gson.JSON, err error) {
	if this.PageShow == nil {
		return gson.JSON{}, errors.New("页面为空")
	}
	defer func() {
		if r := recover(); r != nil {
			err = errors.New("Runjs错误")
		}
	}()
	this.PageShow.Activate()
	ev = this.PageShow.MustEval(`()=>{var Rdata={};var DefData="` + DefData + `";` + js + `
	return Rdata}`)
	return ev, nil
}

// CkDown 检测下载，检测是否下载完成
func (this *Browser) CkDown(savePath string, saveid int) {
	log.Println("CkDown检测下载")
	if this.Status.Dn != 0 {
		log.Println("Dn不为0返回")
		return
	}
	if this.PageDown != nil {
		this.PageDown.Activate()
	} else {
		this.PageDown = this.MainBrowser.MustPage("chrome://downloads/")
	}
	if this.IsCkDown {
		log.Println("CkDown检测下载,正在检测中,退出")
		return
	}
	this.Status.IsCkDown = true
	defer func() {
		this.Status.IsCkDown = false
		if err := recover(); err != nil {
			this.Status.Dn = -1
			log.Println("Down检测下载错误,捕获了异常", err)
			return
		}
		this.ClosePage()
		this.PageDown.MustEval(`()=>{try{
    document.querySelector("body > downloads-manager").shadowRoot.querySelector("#frb0").shadowRoot.querySelector("#cancel").click();
}catch (error){}
try {
    document.querySelector("body > downloads-manager").shadowRoot.querySelector("#toolbar").shadowRoot.querySelector("#clearAll").click()
} catch (error) {}
try {
    document.querySelector("body > downloads-manager").shadowRoot.querySelector("#toolbar").shadowRoot.querySelector("#moreActions").shadowRoot.querySelector("#icon").click()
    document.querySelector("body > downloads-manager").shadowRoot.querySelector("#toolbar").shadowRoot.querySelector("#moreActionsMenu > button.dropdown-item.clear-all").click()
}catch (error) {}
}`)
		this.PageDown.Reload()
	}()
	this.Status.DownloadNum = 0
	maxnum := 0
	status := ""
	filename := ""
	isdone := ""
	url := ""
	isClearPage := false //有下载了就清除页面
	for {
		if this.Status.IsDownload && !isClearPage {
			isClearPage = true
			this.ClosePage()
		}
		if this.Ctx.Err() != nil {
			panic("任务取消")
		}
		if this.Status.Dn != 0 {
			return
		}
		if this.Status.IsPause {
			this.Status.DownloadNum = 0
		}
		maxnum = this.Status.DownloadMax
		if maxnum == 0 {
			maxnum = 15
		}
		log.Println("CkDown检测下载", this.Status.DownloadNum, "/", maxnum)
		if this.Status.DownloadNum > maxnum {
			this.Status.Dn = -1
			this.Status.Msg = "下载超时，失败"
			log.Println("下载超时，失败")
			return
		}
		if this.Status.DownloadNum > 3 && this.Status.IsDownload {
			this.Status.Dn = -1
			this.Status.Msg = "下载速度过慢"
		}
		js := this.PageDown.MustEval(`()=>{
var data="";var filename="";var isdone="";var url = "";
try{
    data=document.querySelector("body > downloads-manager").shadowRoot.querySelector("#frb0").shadowRoot.querySelector("#details").innerText;
    if(data.indexOf("继续")!=-1){
        document.querySelector("body > downloads-manager").shadowRoot.querySelector("#frb0").shadowRoot.querySelector("#pauseOrResume").click();
    }
    filename=document.querySelector("body > downloads-manager").shadowRoot.querySelector("#frb0").shadowRoot.querySelector("#title-area").innerText;
    if(document.querySelector("body > downloads-manager").shadowRoot.querySelector("#frb0").shadowRoot.querySelector("#show-in-folder").getAttribute("hidden")==null){
        isdone="ok";
    }
    url=document.querySelector("body > downloads-manager").shadowRoot.querySelector("#frb0").shadowRoot.querySelector("#url").href;
}catch(e){}
Rdata={
    "data":data,
    "filename":filename,
    "isdone":isdone,
    "url":url
};
return Rdata}`)
		status = js.Get("data").String()
		filename = js.Get("filename").String()
		isdone = js.Get("isdone").String()
		url = js.Get("url").String()
		fmt.Println("检测下载信息：", status, filename, url)
		if gstr.Contains(status, "还剩") || gstr.Contains(status, "B/s") {
			this.Status.IsDownload = true
			this.Status.DownloadNum = 0
		}
		if gstr.Contains(status, "在文件夹中显示") || isdone == "ok" {
			this.Status.IsDownload = true
			this.Status.DownloadNum = 0
			err := MoveFile(filename, savePath, saveid)
			if err != nil {
				log.Println("文件移动失败", err)
				this.Status.Dn = -1
				this.Status.Msg = err.Error()
			} else {
				log.Println("文件下载并上传成功")
				this.Status.Dn = 6
				this.Status.Msg = "下载成功"
			}
			return
		}
		this.Status.DownloadNum++
		time.Sleep(time.Second * 1)
	}
	return
}

// CkHtml 检查网页html
func (this *Browser) CkHtml(savePath string, saveid int) {
	log.Println("CkHtml检测下载")
	this.Status.IsCkDown = true
	if this.IsCkDown {
		log.Println("CkDown检测下载,正在检测中")
		return
	}
	this.IsCkDown = true

	defer func() {
		this.IsCkDown = false
		this.Status.IsCkDown = false
		if err := recover(); err != nil {
			this.Status.Dn = -1
			this.Status.Msg = "CkHtml检测下载错误"
			return
		}
	}()
	this.Status.DownloadNum = 0
	maxnum := 0
	Dn := 0
	Msg := ""
	Html := ""
	for {
		if this.Ctx.Err() != nil {
			return
		}
		if this.Status.Dn != 0 {
			return
		}
		maxnum = this.Status.DownloadMax
		if maxnum == 0 {
			maxnum = 15
		}

		log.Println("CkHtml检测下载", this.Status.DownloadNum, "/", maxnum)
		if this.Status.DownloadNum > maxnum {
			if Html == "" {
				this.Status.Dn = -1
				this.Status.Msg = "下载超时，失败"
				log.Println("下载超时，失败")
				return
			}
			err := UploadByte(savePath+"/"+gconv.String(saveid)+".htm", []byte(Html))
			if err != nil {
				log.Println("网页上传失败", err)
				this.Status.Dn = -1
				this.Status.Msg = err.Error()
			} else {
				log.Println("网页上传成功")
				this.Status.Dn = 6
				this.Status.Msg = "下载成功"
			}
			return
		}

		js := this.PageShow.MustEval(`()=>{

//如果页面是xml就返回0
if(document.documentElement.innerHTML.indexOf("This XML file does not appear to have")!==-1 && location.href.toLowerCase().indexOf(".xml")!==-1){
    Rdata={Dn:1,Msg:"xml文件"}
}else{
    //let res=CkHtml(document.documentElement.innerText);


    const originalHTML = document.documentElement.outerHTML;

// 使用DOMParser解析为文档对象
    const parser = new DOMParser();
    const doc = parser.parseFromString(originalHTML, 'text/html');

// 移除所有<script>标签
    doc.querySelectorAll('script').forEach(script => script.remove());

// 获取处理后的HTML字符串
    const cleanHTML = doc.documentElement.outerHTML;

    let res=CkHtml(cleanHTML);


    console.log(res)
    Rdata=res;
    if(location.href.indexOf("frontiersin.org")>-1){
        Rdata={Dn:0,Msg:"frontiersin.org"}
    }
}
return Rdata}`)
		Dn = js.Get("Dn").Int()
		Msg = js.Get("Msg").String()
		htmltem := this.PageShow.MustHTML()
		log.Println("CkHtml状态==============", Dn, Msg, len(htmltem))
		//这里直接最大值然后保存
		if this.Status.Save || Dn == 6 {
			log.Println("CkHtml 手动保存或者检测Dn6")
			Html = htmltem
			this.Status.DownloadNum = maxnum + 1
			continue
		}
		if Dn < 0 {
			Html = ""
			if Dn == -6 {
				this.Status.Dn = Dn
				this.Status.Msg = Msg
				return
			}
		} else {
			if this.PageShow.MustHas("a") == false && Dn == 0 {
				fmt.Print("没有a标签")
			} else {
				if Html == "" || (Html != htmltem && len(htmltem) > len(Html)) {
					log.Println("网页内容有更新")
					Html = htmltem
					this.Status.DownloadNum = 0
				}
				this.Status.DownloadNum++
				time.Sleep(time.Second * 1)
				continue
			}
		}
		this.Status.DownloadNum++
		if this.Status.IsPause {
			fmt.Print(".")
			this.Status.DownloadNum = 0
		}
		time.Sleep(time.Second * 1)
	}
	return
}

// ClickAuth 模拟点击验证
func (this *Browser) ClickAuth() {
	defer func() {
		if err := recover(); err != nil {
			log.Println("模拟点击错误", err)
		}
	}()
	if this.PageShow == nil {
		return
	}
	nostr, _, _ := this.PageInfo()
	str := []string{"Just a moment...", "请稍候…", "ScienceDirect"}
	if !gstr.InArray(str, nostr) {
		return
	}
	fmt.Println("模拟点击")
	var hwnd uintptr
	wname, e := syscall.UTF16PtrFromString(nostr + " - Google Chrome")
	if e != nil {
		return
	}
	r1, _, _ := syscall.SyscallN(findWindow.Addr(), 0, uintptr(unsafe.Pointer(wname)))
	hwnd = r1
	if hwnd == 0 {
		return
	}

	var (
		rx int
		ry int
	)
	log.Println("鼠标点击验证", nostr)
	switch nostr {
	case "Just a moment...":
		rx = grand.N(210, 290)
		ry = grand.N(367, 377)
	case "ScienceDirect":
		rx = grand.N(300, 370)
		ry = grand.N(312, 320)
	case "请稍候…":
		rx = grand.N(44, 152)
		ry = grand.N(370, 380)
	default:
		return
	}
	log.Println("鼠标点击验证开始点击", nostr)

	msgDown := uintptr(0x0201) // WM_LBUTTONDOWN
	msgUp := uintptr(0x0202)   // WM_LBUTTONUP

	var pt struct {
		X, Y int32
	}

	pt.X = int32(rx)
	pt.Y = int32(ry)
	lParam := uintptr(pt.Y)<<16 | uintptr(pt.X)
	// 发送鼠标按下消息
	syscall.SyscallN(sendMessage.Addr(), hwnd, msgDown, uintptr(1), lParam)

	// 发送鼠标释放消息
	syscall.SyscallN(sendMessage.Addr(), hwnd, msgUp, 0, lParam)
	time.Sleep(time.Second * 5)
	return
}

// ClickXY  模拟点击，点击页面上的坐标
func (this *Browser) ClickXY(x, y int) {
	defer func() {
		if err := recover(); err != nil {
			log.Println("模拟点击错误", err)
		}
	}()
	if this.PageShow == nil {
		return
	}
	nostr, _, _ := this.PageInfo()
	fmt.Println("模拟点击")
	var hwnd uintptr
	wname, e := syscall.UTF16PtrFromString(nostr + " - Google Chrome")
	if e != nil {
		return
	}
	r1, _, _ := syscall.SyscallN(findWindow.Addr(), 0, uintptr(unsafe.Pointer(wname)))
	hwnd = r1
	if hwnd == 0 {
		return
	}

	msgDown := uintptr(0x0201) // WM_LBUTTONDOWN
	msgUp := uintptr(0x0202)   // WM_LBUTTONUP

	var pt struct {
		X, Y int32
	}

	pt.X = int32(x)
	pt.Y = int32(y)
	lParam := uintptr(pt.Y)<<16 | uintptr(pt.X)
	// 发送鼠标按下消息
	syscall.SyscallN(sendMessage.Addr(), hwnd, msgDown, uintptr(1), lParam)

	// 发送鼠标释放消息
	syscall.SyscallN(sendMessage.Addr(), hwnd, msgUp, 0, lParam)
	time.Sleep(time.Second * 1)
	return
}
